package dao;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import org.hibernate.*;
import hibernate.HibernateUtil;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Restrictions;

import comun.CasillaCorreo;
import comun.Inbox;
import comun.Mensaje;
import comun.OficinaCorreo;
import comun.Usuario;

public class CasillaCorreoDAO 
{	
	private static CasillaCorreoDAO instancia = null;
	private static SessionFactory sf = null;
	protected static EntityManager em;

	public static CasillaCorreoDAO getInstancia() {
		if (instancia == null){
			sf = HibernateUtil.getSessionFactory();
			instancia = new CasillaCorreoDAO();
		}
		return instancia;
	}
	
	public CasillaCorreo getCasillaPorCasilla(CasillaCorreo cc){
		CasillaCorreo casilla = null ;
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		casilla = (CasillaCorreo) criteria.add(Restrictions.eq("nombreCasilla" , cc.getNombreCasilla())).uniqueResult() ;
		session.close();
		return casilla ;
	}
	
	public CasillaCorreo getCasillaPorNombre(String nombreCasilla){
		CasillaCorreo casilla = null ;
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		casilla = (CasillaCorreo) criteria.add(Restrictions.eq("nombreCasilla" , nombreCasilla)).uniqueResult() ;
		session.close();
		return casilla ;
	}
	
	@SuppressWarnings("unchecked")
	public List<CasillaCorreo> getCasillasPorUsuario(Usuario u){
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(Usuario.class);
		List<CasillaCorreo> list = criteria.add(Restrictions.eq("nombreUsuario", u.getNombreUsuario())).list();
		session.close();
		return list;
	}
	
	public ArrayList<CasillaCorreo> getCasillasNombreUsuario(String nombre){
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		ArrayList<CasillaCorreo> casillas = (ArrayList<CasillaCorreo>) criteria.add(Restrictions.eq("nombreUsuario", nombre)).list();
		session.close();
		return casillas;
		
	}
	
	
	@SuppressWarnings("unchecked")
	public List<CasillaCorreo> getAllCasillas(){
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		List<CasillaCorreo> list = (List<CasillaCorreo>) criteria.list();
		session.close();
		return list;
	}
	
	public List<CasillaCorreo> getAllCasillasUsuario2(String usuario){
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(CasillaCorreo.class).add(Restrictions.eq("nombreUsuario", usuario));
		List<CasillaCorreo> list = (List<CasillaCorreo>) criteria.list();
		session.close();
		return list;
	}
	
	public List<CasillaCorreo> getCasillasByUsuario(Usuario usuario){
		Session session = sf.openSession();
		
		List<CasillaCorreo> list = (List<CasillaCorreo>) session.createCriteria(Usuario.class)
		.add(Restrictions.like("nombreUsuario", usuario.getNombreUsuario()))
			.setFetchMode("Casillas", FetchMode.JOIN)
			.list();

		session.close();
		return list;
	}

	/*	
		Curso c = (Curso) session.createCriteria(Curso.class)
			.add(Restrictions.like("numero", curso.getNumero()))
			.setFetchMode("alumnos", FetchMode.JOIN)
			.uniqueResult();
		session.close();
		return c;
	}
*/
	/*
	public Person findByUserName(String username)
    throws SearchException
    {
        Session session = obtainSession();
        try
        {
            List tmp = session.find(
                    "from PersonImpl as p where p.userName = ?",
                    username,
                    Hibernate.STRING
            );

            if (tmp != null)
                return (Person)tmp.get( 0 );
            else
                return null;
        }
        catch( Throwable t )
        {
            log.warn( "Unable to perform person find by username", t );
            throw new SearchException(  "Unable to perform person find by username", t );
        }
        finally
        {
            releaseSession( session );
        }
    }
    */
	public List<CasillaCorreo> getAllCasillasUsuario(String nombreUsuario){
		Session session = sf.openSession();
		System.out.println("abri sesion");
		Criteria criteria = session.createCriteria(CasillaCorreo.class)
		.createCriteria("casillas")
		.add(Restrictions.eq("nombreUsuario",nombreUsuario));
		System.out.println("hice criteria");
		//criteria.add(Restrictions.eq("casillas", nombreCasilla));
		List<CasillaCorreo> list = (List<CasillaCorreo>) criteria.list();
		System.out.println("Voy a cerrar sesion, hice list");
		System.out.println("El tamanio de la lista es: "+list.size());
		session.close();
		return list;
	}

	public List<CasillaCorreo> getCasillasPorUsername(String username){
		Session session = sf.openSession();
		Transaction tx = session.beginTransaction();
		Criteria critUsuario = session.createCriteria(Usuario.class);
		Criteria critCasilla = session.createCriteria(CasillaCorreo.class);

		critCasilla.add( Expression.eq("nombreUsuario", username))
					.setFetchMode("Usuarios", FetchMode.JOIN);
		List<CasillaCorreo> casillas = critCasilla.list();

		System.out.println("Encontre las casillas y son : "+casillas.size());

		tx.commit();
		sf.close();
		return casillas;
	}

// version colo
	
	public List<CasillaCorreo> getCasillaByUsernameColo(String username){
        	Session session = sf.openSession();
        	Query q1 = (Query) session.createQuery(
                		"select c.nombreCasilla from casillas as c "+
                		"where c.nombreUsuario='"+username+"'");
                List<CasillaCorreo> casillas = (List<CasillaCorreo>) q1.getResultList();
                return casillas;

        }
	
	public List<Inbox> getInboxesCasilla(String nombreCasilla)
	{	
		Session session = sf.openSession();
		System.out.println("abri sesion");
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		criteria.setFetchMode(nombreCasilla, FetchMode.JOIN);
		criteria.add(Expression.eq("nombreCasilla",nombreCasilla));		
		System.out.println("hice criteria");		
		CasillaCorreo aux = (CasillaCorreo) criteria.uniqueResult();
		List<Inbox> list = (List<Inbox>) aux.getMensajesInbox();		
		System.out.println("Voy a cerrar sesion, hice list");
		System.out.println("El tamanio de la lista es: "+list.size());
		session.close();
		return list;	
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	public Mensaje getMensajePorID(int idMensaje){
		Mensaje mensaje  = null ;
		Session session = sf.openSession();
		Criteria criteria = session.createCriteria(Mensaje.class);
		mensaje = (Mensaje) criteria.add(Restrictions.eq("idMensaje" , idMensaje)).uniqueResult() ;
		session.close();
		return mensaje ;
	}

	public List<Inbox> getInboxesDeCasilla(String nomCasillaCorreo){
		Session session = sf.openSession();
		System.out.println("abri sesion");
		Criteria criteria = session.createCriteria(CasillaCorreo.class);
		//criteria.createCriteria("casillas");
		criteria.setFetchMode(nomCasillaCorreo, FetchMode.JOIN);
		criteria.add(Expression.eq("nombreCasilla",nomCasillaCorreo));		
		System.out.println("hice criteria");		
		//criteria.add(cRestrictions..eq("casillas", nombreCasilla));
		CasillaCorreo auxCasilla = (CasillaCorreo) criteria.uniqueResult();
		List<Inbox> listaInboxes = (List<Inbox>) auxCasilla.getMensajesInbox() ;
		
		for (Inbox inbox : listaInboxes) 
		{
			inbox.setMensaje(CasillaCorreoDAO.getInstancia().getMensajePorID(inbox.getIdMensajeDelInbox())) ;
		}
		
		System.out.println("Voy a cerrar sesion, hice list");
		System.out.println("El tamanio de la lista es: "+listaInboxes.size());
		session.close();
		return listaInboxes ;
	}
}

